﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using LUC.Services;
using LUC.Domains;
using Grid.Extensions;

namespace LUC.Views
{
	public partial class UserSettings:Form
	{
		public BindingList<Feed> cur_feeds;
		public Feed cur_feed;
		
		string[] colWidth;
		MainView mv;
		
		bool _is_change;
		public bool is_change
		{
			get { return _is_change; }
			set
			{
				_is_change = value;
				((CurrencyManager)this.BindingContext[bs]).Refresh();
			}
		}
		
		public UserSettings():base()
		{
			InitializeComponent();
		}
		public UserSettings(MainView n_mv):this()
		{
			cur_feeds = new BindingList<Feed>();
			foreach (Feed feed in DATA.feeds)
			{
				var temp_feed = new Feed
				{
					id_feed = feed.id_feed,
					id_global = feed.id_global,
					name = feed.name,
					font = feed.font,
					color = feed.color,
					position = feed.position,
					notifications = new BindingList<Notification>()
				};
				foreach (Notification n in feed.notifications)
					temp_feed.notifications.Add(new Notification(n));
				cur_feeds.Add(temp_feed);
			}
			
			mv = n_mv;
			bs.Add(this);
			b_save.DataBindings.Add("Enabled", bs, "is_change");
			b_apply.DataBindings.Add("Enabled", bs, "is_change");
			LoadUSAppearance();
		}
		private void UserSettings_Load(object sender, EventArgs e)
		{
			UpdateFeedSource();
			gb_main_set.SetControlSource(DATA.main_set);
			gb_def_feeds.SetControlSource(DATA.def_f_set);
			gb_def_notifications.SetControlSource(DATA.def_n_set);
			is_change = false;
		}

		void LoadUSAppearance()
		{
			colWidth = Program.luc_set.us_col_width.Split(new string[]{";"}, 
				StringSplitOptions.RemoveEmptyEntries);
			
			if (colWidth.Length != typeof(Notification).GetProperties().Where(
				p=>p.GetCustomAttributes(typeof(DisplayNameAttribute), false).Count() > 0).Count())
			{
				Program.luc_set.us_col_width = "200;25;85;75;110;75;75;50;45;";
				Program.luc_set.Save();
				colWidth = Program.luc_set.us_col_width.Split(new string[] { ";" }, 
					StringSplitOptions.RemoveEmptyEntries);
			}
			
			string[] fsize = Program.luc_set.us_scale.Split(new string[]{";"}, 
					StringSplitOptions.RemoveEmptyEntries);
			if (fsize.Length != 5)
			{
				Program.luc_set.us_scale = "50;50;830;375;120;";
				Program.luc_set.Save();
				fsize = Program.luc_set.us_scale.Split(new string[]{";"}, 
					StringSplitOptions.RemoveEmptyEntries);
			}
			Left = Convert.ToInt32(fsize[0]);
			Top = Convert.ToInt32(fsize[1]);
			Width = Convert.ToInt32(fsize[2]);
			Height = Convert.ToInt32(fsize[3]);
			splitContainer1.SplitterDistance = Convert.ToInt32(fsize[4]);
		}
		
		public void SetFeed(Feed n_cur_feed)
		{
			lb_feeds.SelectedItem = n_cur_feed;
		}
		void UpdateFeedSource()
		{
			lb_feeds.DataSource = cur_feeds;
			lb_feeds.ValueMember = "id_feed";
			lb_feeds.DisplayMember = "name";
		}
		private void UserSettings_KeyDown(object sender, KeyEventArgs e)
		{
			switch (e.KeyCode)
			{
				case Keys.Escape:
					if (!dg_notifications.IsCurrentCellInEditMode)
						b_cancel_Click(null, null);
					break;

				case Keys.Insert:
					if (e.Control)
						b_add_feed_Click(null, null);
					else
						b_add_Click(null, null);
					break;

				case Keys.Delete:
					if (e.Control)
					{
						DelFeed();
					}
					else
					{
						if (!dg_notifications.IsCurrentCellInEditMode)
							DeleteNotification();
					}
					break;

				case Keys.C:
					if (e.Control)
						if (!dg_notifications.IsCurrentCellInEditMode)
							b_copy_Click(null, null);
					break;

				case Keys.S:
					if (e.Control)
						if (!dg_notifications.IsCurrentCellInEditMode)
							b_apply_Click(null, null);
					break;
				case Keys.Up:
					if (e.Alt)
						if (!dg_notifications.IsCurrentCellInEditMode)
							MoveNotification(!dg_notifications.Focused, true);
					break;
				case Keys.Down:
					if (e.Alt)
						if (!dg_notifications.IsCurrentCellInEditMode)
							MoveNotification(!dg_notifications.Focused, false);
					break;
			}
		}

		// FEEDS 

		void AddFeed()
		{
			Feed f = ViewAnyModel.ViewFormQuery("Add new feed", new Feed
				{  
					color = DATA.def_f_set.color,
					font = DATA.def_f_set.font,
					id_global = 1,
					id_feed = Program.luc_set.index_indent
				});
			if (f != null)
			{
				if (DATA.feeds.Count == 0)
				{
					f.position = 0;
					f.id_feed = Program.luc_set.index_indent + 1;
				}
				else
				{
					f.position = DATA.feeds.Max(x => x.position) + 1;
					f.id_feed = DATA.feeds.Max(x => x.id_feed) + 1;
				}
				f.notifications = new BindingList<Notification>();
				cur_feeds.Add(f);
				is_change = true;
				UpdateFeedSource();
				SetFeed((Feed)lb_feeds.Items[lb_feeds.Items.Count - 1]);
			}
		}
		void DelFeed()
		{
			if (lb_feeds.SelectedItem == null)
				return;
			if (MessageBox.Show("You are really want to delete this feed/category?", "Want to delete?",
				MessageBoxButtons.OKCancel, MessageBoxIcon.Question) != DialogResult.OK)
				return;
			cur_feeds.Remove((Feed)lb_feeds.SelectedItem);
			is_change = true;
			UpdateFeedSource();
			if (lb_feeds.Items.Count == 0)
				return;
			SetFeed((Feed)lb_feeds.Items[lb_feeds.Items.Count - 1]);
		}
		void EditFeed()
		{
			if (lb_feeds.SelectedItem == null)
				return;
			Feed f = ViewAnyModel.ViewFormQuery("Edit feed", (Feed)lb_feeds.SelectedItem);
			if (f != null)
			{
				cur_feeds[lb_feeds.SelectedIndex] = f;
				is_change = true;
				UpdateFeedSource();
				SetFeed(f);
			}
		}

		private void b_add_feed_Click(object sender, EventArgs e)
		{
			AddFeed();
		}
		private void b_del_feed_Click(object sender, EventArgs e)
		{
			DelFeed();
		}
		private void lb_feeds_MouseDoubleClick(object sender, MouseEventArgs e)
		{
			EditFeed();
		}
		private void lb_feeds_KeyDown(object sender, KeyEventArgs e)
		{
			switch (e.KeyCode)
			{
				case Keys.F2:
					EditFeed();
					break;
			}
		}

		private void lb_feeds_SelectedValueChanged(object sender, EventArgs e)
		{
			if (cur_feed == (Feed)lb_feeds.SelectedItem)
				return;
			cur_feed = (Feed)lb_feeds.SelectedItem;
			if (cur_feed == null)
				return;
			dg_notifications.SetDGSource(cur_feed.notifications, colWidth);
			
			cur_feed.notifications.ListChanged += new ListChangedEventHandler(notifications_ListChanged);
		}

		void notifications_ListChanged(object sender, ListChangedEventArgs e)
		{
			((CurrencyManager)(dg_notifications.BindingContext[(BindingList<Notification>)sender])).Refresh();
			is_change = true;
		}

		// NOTIFICATIONS
		
		public void AddNotification()
		{
			cur_feed.notifications.Add(new Notification
			{
				text = " ",
				id_feed = cur_feed.id_feed,
				font = DATA.def_n_set.font,
				color = DATA.def_n_set.color,
				deadline = DateTime.Now.Add(
					new TimeSpan(
						DATA.def_n_set.delta_days,
						DATA.def_n_set.delta_hhmmss.Hour,
						DATA.def_n_set.delta_hhmmss.Minute,
						DATA.def_n_set.delta_hhmmss.Second)),
				increment_days = DATA.def_n_set.inc_days,
				increment_hhmmss = DATA.def_n_set.inc_hhmmss,
				ringed = DATA.def_n_set.is_ringed,
				delete_happen = DATA.def_n_set.is_delete
			});
			if (cur_feed.notifications.Count == 1)
			{
				dg_notifications.SetDGSource(cur_feed.notifications);
				cur_feed.notifications.ListChanged += new ListChangedEventHandler(notifications_ListChanged);
			}
		}
		private void MoveNotification(bool is_button, bool is_up)
		{
			if (dg_notifications.CurrentCell == null)
				return;
			if (is_up)
			{
				if (dg_notifications.CurrentCell.RowIndex == 0) // if first then exit
					return;
			}
			else
			{
				if (dg_notifications.CurrentCell.RowIndex == dg_notifications.RowCount - 1) // if last then exit
					return;
			}
			int r_index = dg_notifications.CurrentCell.RowIndex;
			int c_index = dg_notifications.CurrentCell.ColumnIndex;
			if (is_up)
				cur_feed.notifications.Exchange<Notification>(r_index, r_index - 1);
			else
				cur_feed.notifications.Exchange<Notification>(r_index, r_index + 1);
			
			if (is_button)
				if (is_up)
					r_index--;
				else
					r_index++;
			dg_notifications.CurrentCell = dg_notifications[c_index, r_index];
		}
		private void DeleteNotification()
		{
			if (dg_notifications.CurrentCell == null)
				return;

			List<Notification> notifs = dg_notifications.SelectedCells.Cast<DataGridViewCell>().
			DistinctBy(x => x.OwningRow).Select(x => (Notification)x.OwningRow.DataBoundItem).ToList();
			foreach (var notif in notifs)
				if (!cur_feed.notifications.Remove(notif))
					Raise.Error("There are unknown mystic error!", "Error while deleting!");
			notifs.Clear();
		}

		private void b_add_Click(object sender, EventArgs e)
		{
			if (cur_feed == null)
			{
				MessageBox.Show("Before add a new notification, previously you must change or " +
				"create feed/category!", "Can't add notification!",
				MessageBoxButtons.OK, MessageBoxIcon.Information);
				return;	
			}
			AddNotification();
		}
		private void b_copy_Click(object sender, EventArgs e)
		{
			if (dg_notifications.CurrentCell == null)
				return;
			cur_feed.notifications.Add(new Notification((Notification)dg_notifications.CurrentRow.DataBoundItem));
			
			dg_notifications.CurrentCell = dg_notifications[0, dg_notifications.Rows.Count - 1];
			dg_notifications.Focus();
		}
		private void b_del_Click(object sender, EventArgs e)
		{
			DeleteNotification();
		}

		private void b_up_Click(object sender, EventArgs e)
		{
			MoveNotification(true, true);
		}
		private void b_down_Click(object sender, EventArgs e)
		{
			MoveNotification(true, false);
		}
		
		// OTHER LOGIC
		
		void SaveAll()
		{
			DATA.SaveDefSet();
			DATA.SaveFeeds(cur_feeds);

			mv.Redraw();
			is_change = false;
		}
		private void b_apply_Click(object sender, EventArgs e)
		{
			SaveAll();
		}
		private void b_save_Click(object sender, EventArgs e)
		{
			SaveAll(); 
			Close();
		}
		private void b_cancel_Click(object sender, EventArgs e)
		{
			Close();
		}

		private void UserSettings_FormClosing(object sender, FormClosingEventArgs e)
		{
			SaveUSAppearance();
			if (is_change)
				switch (MessageBox.Show("Save changes?", "Changes do not save!", MessageBoxButtons.YesNoCancel,
				MessageBoxIcon.Question))
				{
					case DialogResult.No:
						mv.Redraw();
						e.Cancel = false;
						break;
					case DialogResult.Yes:
						SaveAll(); 
						mv.Redraw();
						e.Cancel = false;
						break;
					case DialogResult.Cancel:
						e.Cancel = true;
						break;
				}
			else
				e.Cancel = false;
		}
		void SaveUSAppearance()
		{
			StringBuilder sb = new StringBuilder();
			for (int i = 0; i < dg_notifications.Columns.Count; i++)
				sb.Append(dg_notifications.Columns[i].Width.ToString()).Append(";");
			if (sb.Length != 0)
				Program.luc_set.us_col_width = sb.ToString();
			sb = new StringBuilder();
			Program.luc_set.us_scale =  
				sb.Append(Left).Append(";").
				Append(Top).Append(";").
				Append(Width).Append(";").
				Append(Height).Append(";").
				Append(splitContainer1.SplitterDistance).ToString();
			Program.luc_set.Save();
		}

		private void dg_notifications_CellValueChanged(object sender, DataGridViewCellEventArgs e)
		{
			is_change = true;
		}

	}
}